home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
lpmud312.tar
/
lpmud312
/
parse_old.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-11
|
27KB
|
1,054 lines
/*
Pattern Parser package for LPmud, JnA 1990
Ver 2.0
If you have questions or complaints about this code please refer them
to jna@cd.chalmers.se
This is the old version of parse_command() used in compatibility mode.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "lint.h"
#include "interpret.h"
#include "config.h"
#include "object.h"
#include "wiz_list.h"
#define VALUE struct svalue
#define OBJECT struct object
#define VECTOR struct vector
#define SVALUE struct svalue
#define LVALUE struct svalue
extern char *string_copy PROT((char *)), *xalloc PROT((int));
extern int o_flag, d_flag; /* for debugging purposes */
extern SVALUE const0, const1;
#ifndef tolower /* On some systems this is a function */
extern int tolower PROT((int));
#endif
#ifdef COMPAT_MODE
/*****************************************************
This is the parser
Left to do 910723:
Fix so alternatives possible after %s in a pattern
*/
/*
Doc for LPC function
int parse_command(string,ob/arr,string,destargs...)
parse Returns 1 if pattern matches
string Given command
ob/arr if arr
array holding the accessible objects
if ob
object from which to recurse and create
the list of accessible objects, normally
ob = environment(this_player())
string Parsepattern as list of words and formats:
Example string = " 'get' / 'take' %i "
Syntax:
'word' obligatory text
[word] optional text
/ Alternative marker
%o Single item, object
%l Single living object
%s Any text
%w Any word
%p Preposition
%i Any items
%d Number 0- or tx(0-99)
destargs This is the list of result variables as in sscanf
One variable is needed for each %_
The return types of different %_ is:
%o Returns an object
%l Returns an object
%s Returns a string of words
%w Returns a string of one word
%p Can on entry hold a list of word in array
or an empty variable
Returns:
if empty variable: a string
if array: array[0]=matched word
%i Returns a special array on the form:
[0] = (int) +(wanted) -(order) 0(all)
[1..n] (object) Objectpointers
%d Returns a number
Example:
parse_command("take apple",environment(this_player()),
" 'get' / 'take' %i ",items);
*/
/* Hardcoded function names to call in LPC objects
*/
#define QIDFUNC "id" /* Func to query in objects to ack name */
#define QPLURIDFUNC "plural_id" /* As Id but pluralform of name */
#define QADJFUNC "adjectiv_id" /* As Id but ack adjectiv not name */
#define QSHORTFUNC "short" /* Objects shortdescription */
#define EQ(x,y) (strcmp(x,y)==0)
#define EQN(x,y) (strncmp(x,y,strlen(x))==0)
#define EMPTY(x) (strcmp(x,"")==0)
#define COPY(x) (strcpy((char*)xalloc(strlen(x)+1),x))
#define KLUDGELEN 200 /* How long should strings be */
struct altern_objects {
OBJECT *ao_obj;
struct altern_objects *next;
};
int gDebug=0;
char gMword[KLUDGELEN]; /* Text inom '' och [] */
char gFword[KLUDGELEN]; /* Temp word gotten by getfirst() */
struct altern_objects *gOblist; /* List of accessible objects */
char gAdjective[4*KLUDGELEN]; /* all adjectives before objname */
LVALUE *gCarg; /* Current argument to %_ */
int gWantnum; /* Number of wanted items 0 = all */
struct altern_objects *gPobjects; /* List of parsed objects */
LVALUE *gTxarg; /* Argument of LPCvariable to store %s */
LVALUE *gForprepos; /* Save arg* here for findprepos */
LVALUE *gTopStack; /* arg* to arg after my last */
#define EP 0 /* End Parse marker */
#define SI 1 /* %o single item */
#define IT 2 /* %i items */
#define US 3 /* %l single living object */
#define PP 4 /* %p prepositions */
#define TX 5 /* %s string of words */
#define DTX 6 /* 'word' */
#define OTX 7 /* [word] */
#define ALT 8 /* / alternates */
#define W1 9 /* %w string of one word */
#define NUM 10 /* %d integer */
/* Search string in reverse order, I should replace it with strrchr I know :)
*/
char *backstrchr (apa, ch)
char *apa;
char ch;
{
char *sp;
sp = &apa[strlen(apa)];
while (sp>apa) {
if (*sp==ch) return sp+1;
sp--;
}
return 0;
}
/* Convert string to lowercase
*/
char *lowercase (apa)
char *apa;
{
char *bepa;
bepa = apa;
while (*bepa) {
if ((*bepa>'A') && (*bepa<'a')) (*bepa)+='a'-'A';
bepa++;
}
return apa;
}
/* Add all objects in the inventory of 'first' and itself to the list 'parent'
antal holds the number of elements in the 'parent' list.
*/
void fixlist (first, parent, antal)
OBJECT *first;
struct altern_objects **parent;
int *antal;
{
OBJECT *cur;
struct altern_objects *this,*taill;
cur=first; this= *parent;
if (!cur) return;
while (cur) {
if (cur->contains) fixlist(cur->contains,&this,antal);
taill=this;
this=(struct altern_objects *) xalloc(sizeof(struct altern_objects));
this->ao_obj=cur; (*antal)++;
add_ref(cur,"parse->fixlist");
if (gDebug) fprintf(stderr," Obj:%s ,",cur->name);
this->next=taill; cur=cur->next_inv;
}
*parent=this;
}
/* Create a list of the theoretically accessible objects from 'src'
*/
int makeobjlist (alist, src)
struct altern_objects **alist;
OBJECT *src;
{
OBJECT *env,*cur;
struct altern_objects *this;
int cnt;
*alist=0;
if (!src) env=command_giver->super;
else env=src;
if (!env) return 0;
if (gDebug) fprintf(stderr,"Make list: %s\n",env->name);
if (!(env->contains)) return 0;
cur=env->contains;
this=0; cnt=0;
fixlist(cur,&this,&cnt); *alist=this;
return cnt;
}
/* Routines to use for alternate filters
*/
/* Return number of objects in the list
*/
int itnumalt()
{
int ant;
struct altern_objects *ao;
ant=0; ao=gPobjects;
while (ao) {
ant++;
ao=ao->next;
}
return ant;
}
/* Return a pointer to the numbered element of the list
*/
OBJECT *italt (a)
int a;
{
int ant;
struct altern_objects *ao;
ant=0; ao=gPobjects;
while (ao) {
ant++;
if (ant==a) return ao->ao_obj;
ao=ao->next;
}
return 0;
}
/* Free the list, parameter bas is obsolete
*/
void italt_new ()
{
/* Free p} altern_objects listan */
struct altern_objects *ao;
struct altern_objects *ao2;
if (gDebug) fprintf(stderr,"Clearing italt\n");
ao2=ao=gPobjects; gPobjects=0;
while (ao) {
ao=ao->next;
free_object(ao2->ao_obj,"parse->italt_new()");
free((char *)ao2);
ao2=ao;
}
}
/* Create the list as all the theoretically accessible objects
*/
void italt_loadall()
{
if (gPobjects) italt_new();
makeobjlist(&gPobjects,0);
}
/* Put an object at the end of the list
*/
void italt_put (obj)
OBJECT *obj;
{
struct altern_objects *ao,*old;
if (gDebug) fprintf(stderr,"Putting: %s",obj->name);
ao=gPobjects; old=ao;
while (ao) {
old=ao; ao=ao->next;
}
ao=(struct altern_objects *) xalloc(sizeof(struct altern_objects));
if (old) old->next=ao;
else gPobjects=ao;
ao->ao_obj=obj; ao->next=0;
add_ref(obj,"parse->italt_put()");
if (gDebug) fprintf(stderr,"..done\n");
}
/* Put first word of cmd in gFword and point to next word
*/
char *getfirst (cmd)
char **cmd;
{
int pos,inqoute;
char ch,*st;
st= *cmd; strcpy(gFword,""); if (st[0]==0) return gFword;
ch=' '; pos=0; inqoute=0;
while ((st[0]<=' ') && (st[0])) st++; /* Skip leading spaces */
if ((st[0]=='\'') || (st[0]=='[')) {
inqoute=1; ch=st[0]; gFword[0]=st[0]; pos=1; st++;
}
if (ch=='[') ch=']';
while ((pos<(KLUDGELEN-1)) && (st[0]) && (st[0]!=ch)) {
gFword[pos++]=st[0]; st++;
if ((st[0]) && (st[0]<' ')) st[0]=' '; /* Replace ctrl chars */
}
if ((inqoute) && (pos<(KLUDGELEN-1))) {
gFword[pos++]=ch; if (st[0]) st++;
}
gFword[pos]=0; /* fprintf(stderr,"{%s}",gFword); */
*cmd=st;
return gFword;
}
/* Put first word of cmd in gFword
without incrementing the callers pointer in the command string
*/
char *lookfirst (cmd)
char *cmd;
{
return getfirst(&cmd);
}
/* Call object function in LPC
*/
int call_obj (fnamn, on, apa)
char *fnamn;
OBJECT *on;
char *apa;
{
struct svalue *ret;
if (gDebug) fprintf(stderr,"Calling %s in %s with %s\n",fnamn,on->name,apa);
push_constant_string(apa);
ret = apply(fnamn,on,1);
if (!ret) return 0;
if ( ret->type == T_NUMBER) return ret->u.number;
return 0;
}
/* Change a noun in pluralform to a noun in singularform
*/
char *singfix (str)
char *str;
{
static char sing[KLUDGELEN];
char *sp;
int sl;
sl=strlen(str); if (sl<2) return str;
sp= &str[sl-3]; strcpy(sing,str); sing[sl-3]=0;
if (gDebug) fprintf(stderr,"To singular (%s) end(%s) begin(%s)\n",str,sp,sing);
if (EQ(str,"corpses")) return "corpse";
if (EQ(sp,"ses")) return strcat(sing,"s");
else if (EQ(sp,"xes")) return strcat(sing,"x");
else if (EQ(sp,"hes")) return strcat(sing,"h");
else if (EQ(sp,"ies")) return strcat(sing,"y");
else if (EQ(sp,"ves")) return strcat(sing,"fe");
else if (sp[2]=='s') {
strcat(sing,sp); sing[sl-1]=0;
return sing;
}
if (EQ(str,"teeth")) return "tooth";
if (EQ(str,"feet")) return "foot";
if (EQ(str,"men")) return "man";
if (EQ(str,"women")) return "woman";
if (EQ(str,"children")) return "child";
if (EQ(str,"sheep")) return "sheep";
return str;
}
/* Checks with obj in gOblist to see if it accepts all gAdjectives in adjs
Used when name of object not known, i.e cmds like: 'get all the red ones'
if func QADJFUNC doesn't exist in obj last word of QSHORTFUNC is used
as object name and set as suffix to the adjective in call to id()
*/
int matchadjective (adjs)
char *adjs;
{
char ad[KLUDGELEN],tot[2*KLUDGELEN],*sp,*sp2;
struct altern_objects *ao;
OBJECT *on;
struct svalue *ret;
ao=gOblist;
while (ao) {
on=ao->ao_obj;
sp=adjs;
while ((on) && (sp) && (*sp)) {
while (*sp==' ') sp++;
sp2=strchr(sp,' ');
if (sp2) {
*sp2=0;
strcpy(ad,sp); *sp2=' '; sp=sp2;
if (!call_obj(QADJFUNC,on,ad)) on=0; /* Not ok */
}
sp=sp2;
}
if (on) italt_put(on);
else {
on=ao->ao_obj;
ret = apply(QSHORTFUNC,on,0);
if (ret->type==T_STRING) {
sp=ret->u.string; sp2=backstrchr(sp,' ');
if (sp2) sp=sp2;
sprintf(tot,"%s%s",adjs,sp); lowercase(tot);
if (!call_obj(QIDFUNC,on,tot)) on=0;
}
else on=0;
}
if (on) italt_put(on);
ao=ao->next;
}
return itnumalt();
}
/* Decide if a word is a general word of type: those, ones
*/
int check_for_general (onam, plur)
char *onam;
int plur;
{
static char* plurpron[] = {"those","them","these","ones","$"};
static char* singpron[] = {"this","one","it","$"};
int ilop;
if (EMPTY(onam)) return 0;
if (plur) {
ilop=0;
while (!EQ(plurpron[ilop],"$")) if (EQ(plurpron[ilop++],onam)) return 1;
}
else {
ilop=0;
while (!EQ(singpron[ilop],"$")) if (EQ(singpron[ilop++],onam)) return 1;
}
return 0;
}
int order_num (wd)
char *wd;
{ /* Only positive numbers and zero */
static char *onums[] = {"first","second","third","fourth","fifth","sixth",
"seventh","eighth","nineth","tenth",
"eleventh","twelfth","thirteenth","fourteenth","fifteenth","sixteenth",
"seventeenth","eighteenth","nineteenth","dummy"};
static char *onumt[] = {"twenty","thirty","forty","fifty","sixty","seventy",
"eighty","ninety"};
static char *onumta[] = {"twentieth","thirtieth","fortieth","fiftieth","sixtieth","seventieth",
"eightieth","ninetieth"};
char ns[KLUDGELEN];
int ilop,nm;
if (EMPTY(wd)) return -1;
for (ilop=1;ilop<20;ilop++) {
if (EQ(onums[ilop-1],wd)) return ilop;
}
for (nm=0;nm<8;nm++) for (ilop=0;ilop<9;ilop++) {
if (ilop>0) {
sprintf(ns,"%s%s",onumt[nm],onums[ilop-1]);
if (EQ(ns,wd)) return 20+nm*10+(ilop);
} else
if (EQ(onumta[nm],wd)) return 20+nm*10+(ilop);
}
return -1;
}
int numeric (wd)
char *wd;
{ /* Only positive numbers and zero */
static char *nums[] = {"one","two","three","four","five","six",
"seven","eight","nine","ten",
"eleven","twelve","thirteen","fourteen","fifteen","sixteen",
"seventeen","eighteen","nineteen"};
static char *numt[] = {"twenty","thirty","forty","fifty","sixty","seventy",
"eighty","ninety"};
char ns[KLUDGELEN];
int ilop,nm;
if (EMPTY(wd)) return -1;
if (sscanf(wd,"%d",&nm)) return (nm>=0) ? nm : -1;
if ((EQ(wd,"a")) || (EQ(wd,"an"))) return 1;
for (ilop=1;ilop<20;ilop++) if (EQ(nums[ilop-1],wd)) return ilop;
for (nm=0;nm<8;nm++) for (ilop=0;ilop<9;ilop++) {
if (ilop>0) {
sprintf(ns,"%s%s",numt[nm],nums[ilop-1]);
if (EQ(ns,wd)) return 20+nm*10+(ilop);
}
else
if (EQ(numt[nm],wd)) return 20+nm*10+(ilop);
}
return -1;
}
/* Searches commandstring for "adj1 adj2 ... adjN objectname"
Stores words before name in string: gAdjective, as "adj1 adj2 adj3 "
*/
OBJECT *matchobject2 (cmd, plur)
char **cmd;
int plur;
{
OBJECT *on;
struct altern_objects *ao;
char *st,*ocmd,totname[2*KLUDGELEN],tot2[2*KLUDGELEN];
ocmd= *cmd; strcpy(gAdjective,"");
st=lowercase(getfirst(cmd));
while (st[0]) {
if (check_for_general(st,plur)) {
if (matchadjective(gAdjective)) return italt(1);
}
sprintf(totname,"%s%s",gAdjective,st);
if (plur) sprintf(tot2,"%s%s",gAdjective,singfix(st));
ao=gOblist;
while (ao) {
on=0;
if (plur) {
if (call_obj(QPLURIDFUNC,ao->ao_obj,totname)) on=ao->ao_obj;
else if (call_obj(QIDFUNC,ao->ao_obj,tot2)) on=ao->ao_obj;
}
else if (call_obj(QIDFUNC,ao->ao_obj,totname)) on=ao->ao_obj;
if (on) italt_put(on);
ao=ao->next;
}
if (!itnumalt()) {
strcat(gAdjective,st); strcat(gAdjective," ");
st=lowercase(getfirst(cmd));
}
else st[0]=0;
}
if (itnumalt()) return italt(1);
*cmd=ocmd; return 0;
}
/* Search the command for valid object description
*/
OBJECT *finditem (cmd, plur)
char **cmd;
int plur;
{
int nm;
OBJECT *pn;
char *ocmd,w1[KLUDGELEN];
ocmd= *cmd; strcpy(w1,lowercase(getfirst(cmd)));
if (gDebug) fprintf(stderr,"FO (plur=%d): %s\n",plur,ocmd);
italt_new(); /* Clear alternate list */
gWantnum=1; /* Antal objekt som anv{ndaren vill ta */
if (EMPTY(w1)) {
*cmd=ocmd;
return 0;
}
/* Must be hardcode skipped for recursive with plural
*/
if (EQ("the",w1)) {
if (gDebug) fprintf(stderr,"Skip 'the'\n");
*cmd=ocmd; getfirst(cmd);
if ((pn=finditem(cmd,plur))) return pn;
else { *cmd=ocmd; return 0; }
}
/* Check things like: some <objname>
*/
else if ((EQ("some",w1)) && (plur==0)) {
*cmd=ocmd; getfirst(cmd);
/* Skip of in : some of the bottles */
if (EQ(lowercase(lookfirst(*cmd)),"of")) getfirst(cmd);
nm = random_number(6) + 2; /* some objects are random:2-7 */
if (gDebug) fprintf(stderr,"some rnd = %d\n",nm);
if ((pn=finditem(cmd,1))) {
gWantnum=nm;
return pn;
}
}
/* Check things like: three <objname>
*/
else if ( (plur==0) && ((nm=numeric(w1))>0) ) {
if (gDebug) fprintf(stderr,"Numeral: %d (%s)\n",nm,w1);
*cmd=ocmd; getfirst(cmd);
/* Skip of in : two of the bottles */
if (EQ(lowercase(lookfirst(*cmd)),"of")) getfirst(cmd);
if ((pn=finditem(cmd,nm-1))) {
gWantnum=nm; return pn;
}
}
/* Check things like: third <objname>
*/
else if ( (plur==0) && ((nm=order_num(w1))>0) ) {
if (gDebug) fprintf(stderr,"Order: %d (%s)\n",nm,w1);
*cmd=ocmd; getfirst(cmd);
/* Skip of in : second of the bottles */
if (EQ(lowercase(lookfirst(*cmd)),"of")) {
getfirst(cmd);
if ((pn=finditem(cmd,1))) { /* Fix second of the bottles */
gWantnum= -nm; return pn;
}
}
else {
if ((pn=finditem(cmd,0))) { /* Fix second bottle */
gWantnum = -nm; return pn;
}
}
}
/* Check things like: all <objname>
*/
else if ((EQ("all",w1)) && (plur==0)) {
if (gDebug) fprintf(stderr,"All found\n");
*cmd=ocmd; getfirst(cmd);
/* Skip of in : all of the bottles */
if (EQ(lowercase(lookfirst(*cmd)),"of")) { getfirst(cmd); }
if ((pn=finditem(cmd,1))) { /* Handle: get all apples */
gWantnum=0; /* Antal objekt som anvandaren vill ta 0 == all */
return pn;
}
else { /* Handle: get all */
italt_loadall(); pn=(OBJECT *) italt(1);
gWantnum=0; /* Antal objekt som anvandaren vill ta 0 == all */
}
}
/* Search for: adj1 adj2 ... adjN objectname
*/
else {
*cmd=ocmd; if (gDebug) fprintf(stderr,"Objtry: %s\n",ocmd);
if (plur) pn=matchobject2(cmd,plur);
else { /* Standard singular */
pn=matchobject2(cmd,0);
if (!pn) { /* Handle things of type: get apples */
pn=matchobject2(cmd,1);
if (pn) gWantnum = 0; /* Default this to all */
}
}
if (gDebug) fprintf(stderr,"Done matchobject in finditem.\n");
}
if (pn == 0) *cmd=ocmd;
if (gDebug) fprintf(stderr,"Done finditem.\n");
return pn;
}
/* Find match to a %i in pattern
*/
int findobject (cmd)
char **cmd;
{
int nm,s;
OBJECT *ob;
if (finditem(cmd,0)) {
if (gCarg) {
VECTOR *p;
if (gDebug) fprintf(stderr,"Assign array\n");
nm=itnumalt();
p=(VECTOR *)allocate_array(nm+1);
p->item[0].type = T_NUMBER;
p->item[0].u.number = gWantnum;
/* Make array in reverse order from italt() because
makeobjlist() has reversed the order on entry
*/
for (s=1;s<=nm;s++) {
p->item[s].type = T_OBJECT;
p->item[s].u.ob = ob = italt(nm+1-s);
if (!ob) if (gDebug) fprintf(stderr,"No object from italt %d\n",s);
if (ob) add_ref(ob,"parse_command");
}
free_svalue(gCarg->u.lvalue);
gCarg->u.lvalue->type = T_POINTER;
gCarg->u.lvalue->u.vec = p;
gCarg->u.lvalue->u.vec->ref++;
if (gDebug) fprintf(stderr,"Assign array2\n");
}
return 1;
}
return 0;
}
/* Find match to a %l in pattern
*/
OBJECT *findplay (cmd)
char **cmd;
{
OBJECT *pn;
char w1[KLUDGELEN];
strcpy(w1,lowercase(lookfirst(*cmd)));
/* can be fixed later with call to LPC command_giver->query_real_name()
if (EQ(w1,"me")) strcpy(w1,getmyname_jp());
if (EQ(w1,"myself")) strcpy(w1,getmyname_jp());
*/
pn=(OBJECT *) find_living_object(w1, 1); /* Find player by name */
if (pn) {
getfirst(cmd);
if (gCarg) {
free_svalue(gCarg->u.lvalue);
gCarg->u.lvalue->type = T_OBJECT;
gCarg->u.lvalue->u.ob = pn;
add_ref(pn, "parse_command(%l)");
}
}
return pn;
}
/* Find match to %p in pattern when a list of words has been supplied
*/
int findword (cmd, v)
char **cmd;
VALUE *v;
{
char *w;
VECTOR *p;
struct svalue sv;
int cnt,m,f;
w = lookfirst(*cmd); lowercase(w); p=v->u.vec;
cnt=0; m=p->size; f= -1;
while (cnt<m) {
if (p->item[cnt].type == T_STRING) {
if (strcmp(p->item[cnt].u.string,w)==0) {
f=cnt; cnt=m;
}
}
cnt+=1;
}
if (f<0) return 0;
getfirst(cmd);
if (!f) return 1; /* Match and word in first element */
/*
Swap element 0 and f in array
*/
sv=p->item[0]; p->item[0]=p->item[f]; p->item[f]=sv;
return 1;
}
/* Find match to %p in pattern
*/
int findprepos (cmd)
char **cmd;
{
char *w;
static char *hard_prep[] = {"on","in","under","from","behind","beside",0};
SVALUE *v;
int cnt;
if (gForprepos) {
v = gForprepos->u.lvalue;
if ((v != 0) && (v->type == T_POINTER)) return findword(cmd,v);
}
/* No wordlist sent, use hard coded prepositions and return a string
*/
w = lookfirst(*cmd); lowercase(w);
cnt=0; while (hard_prep[cnt]) {
if (strcmp(w,hard_prep[cnt])==0) {
getfirst(cmd); /* Skip this word */
if (gCarg) {
free_svalue(gCarg->u.lvalue);
gCarg->u.lvalue->type = T_STRING;
gCarg->u.lvalue->u.string = string_copy(w);
gCarg->u.lvalue->string_type = STRING_MALLOC;
return 1;
}
}
cnt++;
}
return 0;
}
/* Find match to %o in pattern
*/
int findsingle (cmd)
char **cmd;
{
if (finditem(cmd,0)) {
if ((itnumalt()==1) && (gCarg)) {
free_svalue(gCarg->u.lvalue);
gCarg->u.lvalue->type = T_OBJECT;
gCarg->u.lvalue->u.ob=italt(1);
add_ref(gCarg->u.lvalue->u.ob, "parse_command(%o)");
}
return 1;
}
return 0;
}
/* Get the first parsetype of the pattern
*/
int get1ps (parsep, lin, skip)
char **parsep;
LVALUE **lin;
int skip;
{
char *cod,ch;
int pt;
LVALUE *l;
pt=EP; cod=getfirst(parsep); l= *lin;
ch=cod[0]; if (ch=='%') { ch=tolower(cod[1]); ch=cod[1]; }
switch (ch) {
case 'i':pt=IT; break;
case 'l':pt=US; break;
case 's':pt=TX; break;
case 'w':pt=W1; break;
case 'o':pt=SI; break;
case 'p':pt=PP; break;
case 'd':pt=NUM; break;
case '\'':sscanf(cod,"'%[^\']",gMword); pt=DTX; break;
case '[':sscanf(cod,"\[%[^\135]",gMword); pt=OTX; /* 135 is oct for ] */
if (gMword[strlen(gMword)-1]==']') gMword[strlen(gMword)-1]=0;
break;
case '/':pt=ALT; break;
}
if (gDebug) fprintf(stderr,"(%s,%s,%d,%c)",cod,gMword,pt,ch);
gCarg=0;
if ((skip) || (pt==DTX) || (pt==OTX) || (pt==ALT)) return pt;
if (l != gTopStack) { gForprepos=l; gCarg=l; l++; }
else { gCarg = 0; gForprepos=0; }
*lin=l;
return pt;
}
/* Add word to the string that matches the latest %s
*/
void addword (d, s)
char *d;
char *s;
{
if ((strlen(d)+strlen(s))<(KLUDGELEN-2)) {
if (!EMPTY(d)) strcat(d," ");
strcat(d,s);
}
if (gTxarg) {
free_svalue(gTxarg->u.lvalue);
gTxarg->u.lvalue->type = T_STRING;
gTxarg->u.lvalue->u.string = string_copy(d);
gTxarg->u.lvalue->string_type = STRING_MALLOC;
}
}
/* Main function, called from interpret.c
*/
int parse (cs, ob_or_array, ps, dest_args, num_arg)
char *cs, *ps;
struct svalue *ob_or_array, *dest_args;
int num_arg;
{
/* Arguments:
string Command
ob/arr List of accessible objects or recurse start object
ps parsepattern
destargs lvalues.
num_arg Number of lvalues.
*/
int altflag, /* =1 (true) i altkedja, match har intr{ffat */
txflag, /* = 1 om vi adderar text till str{ng */
ptyp; /* Parsetype %o %i %l %p %s 'word' [word] / %w */
char *parsep; /* Parsepattern */
char *cmd; /* Command to be parsed */
char *ops,*ocs; /* Temporary parse and command */
char tx_jp[KLUDGELEN]; /* Fill up string for %s */
LVALUE *l; /* Argument pointer in dest_args */
int new_routines();
if (ob_or_array->type == T_OBJECT &&
(ob_or_array->u.ob->flags & O_DESTRUCTED))
return 0;
gDebug = 0;
if (gDebug) {
fprintf(stderr,"Hold on to your toes, entering JnAparse. ");
}
/* In mudlib 3.0 we will not have this
*/
if (cs[0]=='@')
error("Unsupported @ construct.\n");
ocs = cmd = (char *) string_copy(cs);
/* Get the accessible objects
*/
if (ob_or_array->type == T_OBJECT) makeobjlist(&gOblist,ob_or_array->u.ob);
else { /* Copy list of given accessible objects in reverse order */
VECTOR *v;
SVALUE *vv;
int cnt;
v=ob_or_array->u.vec; italt_new();
for (cnt=0;cnt<v->size;cnt++) {
vv = &(v->item[v->size-1-cnt]);
if (vv->type==T_OBJECT) italt_put(vv->u.ob);
}
gOblist=gPobjects; gPobjects=0;
}
ops = parsep = (char *) string_copy(ps);
gPobjects=gOblist;
if (gDebug) fprintf(stderr,"Has made list of Acsobjects. %d \n",itnumalt());
if (gDebug) fprintf(stderr,"Parsing: %s, with pattern: %s\n",cmd,parsep);
gPobjects=0;
/* Start parsing
*/
txflag = -1; gCarg = 0; gTxarg = 0; gTopStack = dest_args + num_arg;
l = dest_args;
ptyp=get1ps(&parsep,&l,0); /* Get first pattern from parse */
while (ptyp != EP) {
if (gDebug) fprintf(stderr,"Pattern: %d\n",ptyp);
altflag=0;
switch(ptyp) { /* See which pattern type to search for */
case EP: break;
case SI: if (findsingle(&cmd)) altflag=1; /* %o */ break;
case IT: if (findobject(&cmd)) altflag=1; /* %i */ break;
case US: if (findplay(&cmd)) altflag=1; /* %l */ break;
case PP: if (findprepos(&cmd)) altflag=1; /* %p */ break;
case TX: /* %s */
txflag=1; strcpy(tx_jp,""); gTxarg=gCarg; altflag=1;
break;
case DTX: /* 'word' */
if (EQ(lowercase(gMword),lowercase(lookfirst(cmd)))) {
getfirst(&cmd); altflag=1;
}
break;
case OTX: /* [word] */
if (EQ(lowercase(gMword),lowercase(lookfirst(cmd)))) {
getfirst(&cmd);
}
altflag=1; /* Always take next parsepattern type [word] is opt */
break;
case ALT: /* / */
altflag=1; /* Should not be found here, if so skip it */
case W1: /* %w */
gTxarg=gCarg; strcpy(tx_jp,""); altflag=1;
addword(tx_jp,getfirst(&cmd));
break;
case NUM: /* %d */
if ((altflag=numeric(lookfirst(cmd)))>0) {
if (gCarg) {
free_svalue(gCarg->u.lvalue);
gCarg->u.lvalue->type = T_NUMBER;
gCarg->u.lvalue->u.number = altflag;
}
altflag=1; getfirst(&cmd);
}
break;
}
/* Pattern checked altflag==1 indicates match
*/
if (altflag) { /* Pattern matched, fetch next and end string input */
if (ptyp != TX) txflag = -1; /* End string input if not just started */
ptyp=get1ps(&parsep,&l,0);
while (ptyp == ALT) { /* Skip left over alternatives */
ptyp=get1ps(&parsep,&l,1); /* Skip this pattern */
ptyp=get1ps(&parsep,&l,0); /* Next real pattern or ALT */
}
}
else { /* Pattern did not match */
char *a;
LVALUE *try;
int tmp;
a=parsep; try=l;
tmp=get1ps(&a,&try,0);
if (tmp == ALT) {
ptyp=get1ps(&parsep,&l,0); /* Skip ALT */
ptyp=get1ps(&parsep,&l,0); /* Next real pattern or ALT */
}
else {
if (txflag>=0) { /* %s is defined, add word and try pattern again */
addword(tx_jp,getfirst(&cmd));
}
else break; /* Impossible to match pattern, exit */
}
}
if (gDebug) fprintf(stderr,"Pattern, after: %d\n",ptyp);
}
/* End of pattern reached, what have got? What is left?
*/
if (gDebug) fprintf(stderr,"Pattern ended\n");
if (txflag>=0) { /* It ended with a %s, fill up the string */
while (!EMPTY(cmd)) addword(tx_jp,getfirst(&cmd));
}
if (!EMPTY(cmd)) ptyp=ALT; /* No match so set ptyp != EP */
/* Now clean up our mess, no alloced mem should remain
*/
free(ocs); free(ops);
if (gPobjects) italt_new(); /* Free alternate object list */
if (gOblist) {
gPobjects=gOblist; italt_new(); /* Free list of accessible objects */
}
if (ptyp==EP) {
if (gDebug) fprintf(stderr,"Exiting Jnaparse with match\n");
return 1; /* Successfull match */
}
else {
if (gDebug) fprintf(stderr,"Exiting Jnaparse: No match\n");
return 0; /* No match */
}
}
/*
End of Parser
***************************************************************/
#endif